// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once  // 头文件保护宏，防止重复包含

#include "Accolades/LyraAccoladeDefinition.h"  // 包含荣誉定义
#include "AsyncMixin.h"  // 包含异步混合类
#include "CommonUserWidget.h"  // 包含通用用户控件
#include "GameFramework/GameplayMessageSubsystem.h"  // 包含Gameplay消息子系统

#include "LyraAccoladeHostWidget.generated.h"  // 包含UE生成的代码

class UObject;  // 前向声明UObject类
class USoundBase;  // 前向声明USoundBase类
class UUserWidget;  // 前向声明UUserWidget类
struct FDataRegistryAcquireResult;  // 前向声明数据注册表获取结果结构体
struct FLyraNotificationMessage;  // 前向声明Lyra通知消息结构体

USTRUCT(BlueprintType)  // UE反射结构体，可在蓝图中使用
struct FPendingAccoladeEntry  // 待处理荣誉条目结构体
{
	GENERATED_BODY();  // UE宏，生成反射代码体

	UPROPERTY(BlueprintReadOnly)  // 属性：蓝图只读
	FLyraAccoladeDefinitionRow Row;  // 荣誉定义行

	UPROPERTY(BlueprintReadOnly)  // 属性：蓝图只读
	TObjectPtr<USoundBase> Sound = nullptr;  // 声音对象指针，初始化为空

	UPROPERTY(BlueprintReadOnly)  // 属性：蓝图只读
	TObjectPtr<UObject> Icon = nullptr;  // 图标对象指针，初始化为空

	UPROPERTY()  // 属性
	TObjectPtr<UUserWidget> AllocatedWidget = nullptr;  // 分配的控件指针，初始化为空

	int32 SequenceID = 0;  // 序列ID，初始化为0

	bool bFinishedLoading = false;  // 加载完成标志，初始化为false

	void CancelDisplay();  // 取消显示方法声明
};

/**
 * 
 */
UCLASS(BlueprintType)  // UE反射类，可在蓝图中使用
class ULyraAccoladeHostWidget : public UCommonUserWidget, public FAsyncMixin  // 荣誉宿主控件类，继承自通用用户控件和异步混合类
{
	GENERATED_BODY()  // UE宏，生成反射代码体

public:
	// 位置标签（用于过滤传入消息，仅显示适当位置的荣誉）
	UPROPERTY(EditAnywhere, BlueprintReadOnly)  // 属性：在任何地方可编辑，蓝图只读
	FGameplayTag LocationName;  // 位置名称标签

	//~UUserWidget接口
	virtual void NativeConstruct() override;  // 重写原生构造方法
	virtual void NativeDestruct() override;  // 重写原生析构方法
	//~UUserWidget接口结束

	UFUNCTION(BlueprintImplementableEvent)  // 蓝图可实现事件
	void DestroyAccoladeWidget(UUserWidget* Widget);  // 销毁荣誉控件

	UFUNCTION(BlueprintImplementableEvent)  // 蓝图可实现事件
	UUserWidget* CreateAccoladeWidget(const FPendingAccoladeEntry& Entry);  // 创建荣誉控件
private:
	FGameplayMessageListenerHandle ListenerHandle;  // 游戏消息监听器句柄

	int32 NextDisplaySequenceID = 0;  // 下一个显示序列ID，初始化为0
	int32 AllocatedSequenceID = 0;  // 已分配序列ID，初始化为0

	FTimerHandle NextTimeToReconsiderHandle;  // 下次重新考虑计时器句柄

	// 异步待加载荣誉列表（由于行读取可能顺序错误）
	UPROPERTY(Transient)  // 属性：临时
	TArray<FPendingAccoladeEntry> PendingAccoladeLoads;  // 待加载荣誉数组

	// 待处理荣誉列表（由于一次显示一个的持续时间；列表中的第一个是当前可见的）
	UPROPERTY(Transient)  // 属性：临时
	TArray<FPendingAccoladeEntry> PendingAccoladeDisplays;  // 待显示荣誉数组


	void OnNotificationMessage(FGameplayTag Channel, const FLyraNotificationMessage& Notification);  // 通知消息处理方法
	void OnRegistryLoadCompleted(const FDataRegistryAcquireResult& AccoladeHandle, int32 SequenceID);  // 注册表加载完成处理方法

	void ConsiderLoadedAccolades();  // 考虑已加载荣誉方法
	void PopDisplayedAccolade();  // 弹出显示的荣誉方法
	void ProcessLoadedAccolade(const FPendingAccoladeEntry& Entry);  // 处理已加载荣誉方法
	void DisplayNextAccolade();  // 显示下一个荣誉方法
};